package pt.inescid.components.policyengine.heimdall.pap;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.base.EventRelevance;
import pt.inescid.components.policyengine.heimdall.base.Policy;
import pt.inescid.components.policyengine.heimdall.base.User;
import pt.inescid.components.policyengine.heimdall.commons.DBManager;
import pt.inescid.components.policyengine.heimdall.commons.Log;
import pt.inescid.components.policyengine.heimdall.commons.Utilities;
import pt.inescid.components.policyengine.heimdall.contact.RemoteCommand;
import pt.inescid.components.policyengine.heimdall.contact.RemoteResponse;
import pt.inescid.components.policyengine.heimdall.database.PolicyDAO;
import pt.inescid.components.policyengine.heimdall.pap.base.ModelDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.RuleDefinition;

public class PolicyManager {

	
	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      exportCes       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public static RemoteResponse exportCes(RemoteCommand command) {

		// parameters received:
		// - user id
		// - user model tag
		// - policy text
		// - cesName
		Vector allParameters = command.getMessage();
		long userId = ((Long) allParameters.elementAt(0)).longValue();
		String userModelTag = (String) allParameters.elementAt(1);
		String modelAsText = (String) allParameters.elementAt(2);
		String cesName = (String) allParameters.elementAt(3);
	
		// verify if the user exists
		User currentUser = UserManagerAS.getRecord(userId);
		if (currentUser == null) {
			return (new RemoteResponse(
					RemoteResponse.UNKNOWN_USER_RESPONSE,
					null));
		}
		
		// verify if this ces is already loaded
		ModelDefinition localModel = 
			currentUser.getCesModel(userModelTag, cesName);
		
		// store policy in database
		String localCesModelTag = null;
		if (localModel == null) {
			localCesModelTag = userModelTag + "_" + cesName;
			localModel = new ModelDefinition(localCesModelTag);
			currentUser.addModel(localModel);
			PolicyDAO.insertRecord(userId, 
					Policy.REMOTE_POLICY, 
					cesName,
					localCesModelTag, 
					modelAsText);
		}
		else {
			localCesModelTag = localModel.getTag();
			PolicyDAO.updateRecord(userId, 
					localCesModelTag, 
					modelAsText);
		}

		// load policy into user context
		PolicyParser.updateModel(currentUser, localCesModelTag,
				modelAsText);
		
		// create a new events table
		String eventsTableName = "event_U" +
				Utilities.getFormattedNumber(
						new Long(currentUser.getId()).intValue(), 4) +
						"_" + localCesModelTag;

		PolicyManager.createEventsTable(currentUser, eventsTableName,
				localModel);

		// reply to policy home host
		return (new RemoteResponse(
				RemoteResponse.OK_RESPONSE,
				null));
	} // exportCes
	
	
	
	

	
	
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      storePolicy       =====================
	=============                    =============================
	==============================================================
	=========================================================== */
	public static void storePolicy(User currentUser,
			String userModelTag,
			String policyText)
	throws IOException {
		
		Log.debug(Log.INFO, "Arrived.", "PolicyManager.storePolicy"); 	
		
		// verify if this model is already loaded
		ModelDefinition localModel = 
			currentUser.getModelByTag(userModelTag);
		
		if (localModel == null) {
			localModel = new ModelDefinition(userModelTag);
			currentUser.addModel(localModel);
			PolicyDAO.insertRecord(currentUser.getId(), 
					Policy.LOCAL_POLICY,
					null,
					userModelTag, 
					policyText);
		}
		else {
			PolicyDAO.updateRecord(currentUser.getId(), 
					userModelTag, 
					policyText);
		}
		
		// updateUserContext
		PolicyParser.updateModel(currentUser,userModelTag,policyText);
		
		// create a new events table
		String eventsTableName = "event_U" +
		Utilities.getFormattedNumber(
				new Long(currentUser.getId()).intValue(), 4) +
				"_" + userModelTag;
		
		PolicyManager.createEventsTable(currentUser, eventsTableName,
				localModel);
		
	} // storePolicy
	
	
	
	
	
	/* ===========================================================
	 ==============================================================
	 =============                    =============================
	 =============      createEventsTable =========================
	 =============                    =============================
	 ==============================================================
	 =========================================================== */
	public static void createEventsTable(
			User currentUser,
			String eventsTableName,
			ModelDefinition currentModelDef) {
		Vector allParameters = currentModelDef.getRelevantCesParameters();
		
		String dropQuery = 
			"drop table if exists " + eventsTableName + 
			";\n";
		String createQuery = 
			"create table " + eventsTableName + 
			" (\n" +
			"		id      INT(11) NOT NULL AUTO_INCREMENT,\n" +
			"		info    BLOB default NULL,\n";
		
		EventRelevance currentParameter = null;
		String fieldName = null;
		for (int i = 0; i < allParameters.size(); i++) {
			currentParameter = (EventRelevance) allParameters.elementAt(i);
			
			fieldName = currentParameter.getEventFieldNameForSQL();
			
			createQuery +=
"\t\t" + fieldName +
"\t" + RuleDefinition.SQL_EXPRESSION_VALUE_CODES[currentParameter.getFieldType()] + 
" default NULL,\n";
		}
		
		createQuery +=
"		tag	VARCHAR(255) default NULL,\n" +
"		primary key(id));";
		
		try {
			PreparedStatement ps = DBManager.getConnection().prepareStatement(
					dropQuery);
			ps.execute();
			ps.close();
		}
		catch (SQLException e) {
			Log.debug(Log.ERROR, "Erro SQL: " + e + 
					" - query = " + dropQuery, "PolicyManager.createEventsTable");
		}
		
		try {
			PreparedStatement ps = DBManager.getConnection().prepareStatement(
					createQuery);
			ps.execute();
			ps.close();
		}
		catch (SQLException e) {
			Log.debug(Log.ERROR, "Erro SQL: " + e + 
					" - query = " + createQuery, "PolicyManager.createEventsTable");
		}
	} // createEventsTable
	
	
	public static void main(String[] args) {
		User currentUser = UserManagerAS.getRecord(1);

		try {
			BufferedReader bf =
				new BufferedReader(new FileReader(
					"G:/docs/Projectos/heimdall/policies/" +
					"Policy_O_privacy.xml"));
				
//			BufferedReader bf =
//				new BufferedReader(new FileReader(
//					"D:/docsP/Projectos/heimdall/policies/" +
//					"Policy_H_future.xml"));
//				
			
			String policyText = "";
			String nextLine = null;
			while ((nextLine = bf.readLine()) != null) {
				policyText += nextLine + "\n";
			}
			
			storePolicy(currentUser,"SYG", policyText);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
};